require "digest/sha1"

class User < ActiveRecord::Base
  has_many :ideas, :dependent => :nullify

  validates_presence_of :login, :email
  validates_presence_of :password, :on => :create
  validates_uniqueness_of :login, :activation_code
  validates_length_of :login, :within => 5..20
  validates_length_of :password, :within => 5..20, :allow_nil => true
  validates_confirmation_of :password
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i
  
  before_create :set_activation_code
  before_save :encrypt_password
  
  attr_accessor :password
  
  def active?
  	self.active && self.email_confirmed
  end
  
  def email=(newemail)
    if self.email == newemail
      write_attribute(:email, newemail)
    else
      write_attribute(:email, newemail)
      self.email_confirmed = false
      self.set_activation_code
    end
  end
  
  def full_name
    if first_name && last_name
      return "#{first_name} #{last_name}"
    else
      last_name.nil? ? first_name : last_name
    end
  end
  
  def self.activate(code)
    @user = find(:first, :conditions => [ "activation_code = ?", code ])
    @user.update_attributes({:activation_code => nil, :email_confirmed => true})
  end
  
  def self.login(login, password)
    @user = find(:first, :conditions => [ "login = ? and active = ? and email_confirmed = ?", login, true, true ])
    return nil if @user.blank?
    
    passwd_encrypted = @user.encrypt(password, @user.salt)
    
    if @user.password_encrypted == passwd_encrypted
      @user.update_last_login
      @user.update_remember_login
      return @user
    else
      nil
    end
  end
  
  def self.logout(login)
  	@user = find(:first, :conditions => [ "login = ?", login ])
    return nil if @user.nil?
    
    @user.last_login = Time.now
    @user.remember_login = nil
    
    return @user
  end
  
  def set_activation_code
    return true if self.email_confirmed
    
    self.activation_code = generate_code
    
    # TODO check if key is unique
  end
  
  def generate_code
  	code = "code"
    16.times { code << (i = Kernel.rand(62); i += ((i < 10) ? 48 : ((i < 36) ? 55 : 61 ))).chr }
    return code
  end
  
  def encrypt_password
    return if password.blank?
    self.salt = Digest::SHA1.hexdigest("#{Time.now.to_s}-#{login}") if new_record?
    self.password_encrypted = encrypt(password, self.salt)
  end
  
  def encrypt(password, salt)
  	Digest::SHA1.hexdigest("#{salt}-#{password}")
  end
  
  def update_last_login
  	self.last_login = Time.now
  end
  
  def update_remember_login
  	self.remember_login = 2.weeks.from_now
  end
end
